using System;
using System.Collections.Generic;
using System.IO;
using kk.components.contracts;
using kk.messages.contracts.DataModel;
using LoungeRepo.Core;

namespace kk.belegungsadapter
{
    public class BelegungsAdapter : IBelegungsAdapter
    {
        public void BelegungenZuVorstellung(Request<Vorstellung, IEnumerable<Platzposition>> request)
        {
            IEnumerable<Platzposition> Belegung = LoadBelegung(request.RequestData);

            request.ResponsePin(Belegung);
        }

        public void ProcessReservierungsanfrage(Request<Reservierungsanfrage, string> request)
        {
            using (var LR = new LoungeRepository("BelegungRepo"))
            {
                try
                {

                    var Counter = LR.Load<int>("ReservierungsnummerCounter");
                    LR.Store(Counter ++, "ReservierungsnummerCounter");

                }
                catch (Exception)
                {

                    LR.Store(1, "ReservierungsnummerCounter");
                }
            }

            using(var BelegungsRepo = new LoungeRepository("BelegungRepo"))
            {
                var Reservierungsnummer = "";

                if (CheckReservation(request.RequestData))
                {
                    Reservierungsnummer = "Reservierung_" + BelegungsRepo.Load<int>("ReservierungsnummerCounter").ToString();
                    BelegungsRepo.Store(request.RequestData, Reservierungsnummer);
                    StoreNewReservationToBelegungsPlan(request.RequestData);
                }

                request.ResponsePin(Reservierungsnummer);
            }
        }

        private void StoreNewReservationToBelegungsPlan(Reservierungsanfrage Reservierungsanfrage)
        {
            List<Platzposition> NeuerBelegungsPlan = new List<Platzposition>();

            foreach(var ReservierterPlatz in LoadBelegung(Reservierungsanfrage.Vorstellung))
            {
                NeuerBelegungsPlan.Add(ReservierterPlatz);
            }

            foreach (var AngeforderterPlatz in Reservierungsanfrage.Platzpositionen)
            {
                NeuerBelegungsPlan.Add(AngeforderterPlatz);
            }

            using(var BelegungRepo = new LoungeRepository("BelegungRepo"))
            {
                BelegungRepo.Store(NeuerBelegungsPlan.ToArray(), BuildVorstellungId(Reservierungsanfrage.Vorstellung));
            }
        }

        internal bool CheckReservation(Reservierungsanfrage Reservierungsanfrage)
        {
            foreach (var Platzposition in Reservierungsanfrage.Platzpositionen)
            {
                foreach (var ReservierterPlatz in LoadBelegung(Reservierungsanfrage.Vorstellung))
                {
                    if(Platzposition.Equals(ReservierterPlatz))
                    {
                        return false;
                    }
                }
            }

            return true;
        }

        internal IEnumerable<Platzposition> LoadBelegung(Vorstellung Vorstellung)
        {
            using (var BelegungRepo = new LoungeRepository("BelegungRepo"))
            {
                try
                {
                    return BelegungRepo.Load<IEnumerable<Platzposition>>(BuildVorstellungId(Vorstellung));
                }
                catch (Exception)
                {
                    return new Platzposition[] {};
                }
            }
        }

        internal string BuildVorstellungId(Vorstellung Vorstellung)
        {
            return Vorstellung.Titel + Vorstellung.Termin.Day + Vorstellung.Termin.Month + Vorstellung.Termin.Year + Vorstellung.Termin.Hour + Vorstellung.Termin.Minute + Vorstellung.Saal;
        }
    }
}